#include "DamageComponent.h"

#include "Demo/Character/DemoCharacter.h"
#include "Demo/Character/Enemy.h"
#include "GameFramework/Character.h"
#include "Kismet/KismetSystemLibrary.h"


UDamageComponent::UDamageComponent()
{
	PrimaryComponentTick . bCanEverTick = true;
}

void UDamageComponent::BeginPlay()
{
	Super::BeginPlay();
}

void UDamageComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

void UDamageComponent::Attack(const float DamageValue)
{
	FHitResult HitResult;
	TArray<TEnumAsByte<EObjectTypeQuery>> Type = {
		UEngineTypes::ConvertToObjectType(ECC_Pawn)
	};
	AActor* Owner = GetOwner();
	const FVector Start = Owner -> GetActorLocation();
	const FVector End = Start + Owner -> GetActorForwardVector();
	UKismetSystemLibrary::BoxTraceSingleForObjects(
		GetWorld(), Start, End, FVector(100), Owner -> GetActorRotation(),
		Type, false, TArray<AActor*>({Owner}),
		EDrawDebugTrace::ForDuration, HitResult, true
	);
	AActor* OtherActor = HitResult . GetActor();
	ACharacter* Character = Cast<ACharacter>(OtherActor);
	ADemoCharacter* DemoCharacter = Cast<ADemoCharacter>(Owner);
	if (DemoCharacter)
	{
		DemoCharacter -> PlayAttackSound();
		DemoCharacter -> PlayAttackEffect();
	}
	AEnemy* Enemy = Cast<AEnemy>(Owner);
	if (Enemy)
	{
		Enemy -> PlayAttackSound();
		Enemy -> PlayAttackEffect();
	}
	if (Character)
	{
		Character -> LaunchCharacter(Owner -> GetActorForwardVector() * 1000, false, false);
		UDamageComponent* DamageComponent = Character -> FindComponentByClass<UDamageComponent>();
		if (DamageComponent)
		{
			DamageComponent -> TakeDamage(DamageValue);
		}
		ADemoCharacter* PlayerCharacter = Cast<ADemoCharacter>(Character);
		if (PlayerCharacter)
		{
			PlayerCharacter -> PlayDamageHUD();
		}
	}
}

void UDamageComponent::TakeDamage(const float Value)
{
	AActor* Owner = GetOwner();
	AddHealth(-Value);
	if (GEngine)
	{
		GEngine -> AddOnScreenDebugMessage(-1, 5, FColor::Green, Owner -> GetName() + FString::SanitizeFloat(Health));
	}
	if (IsDeath())
	{
		OnDeath . Broadcast();
	}
}
